package cn.cqautotest.cqviehelper.ui.fragment;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.Window;

import androidx.annotation.RequiresApi;
import androidx.fragment.app.FragmentActivity;

import com.bigkoo.pickerview.builder.OptionsPickerBuilder;
import com.bigkoo.pickerview.view.OptionsPickerView;
import com.blankj.utilcode.util.ArrayUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.google.gson.Gson;
import com.haibin.calendarview.Calendar;
import com.hjq.permissions.OnPermission;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.lcodecore.tkrefreshlayout.RefreshListenerAdapter;
import com.lcodecore.tkrefreshlayout.TwinklingRefreshLayout;
import com.lcodecore.tkrefreshlayout.header.bezierlayout.BezierLayout;
import com.zhuangfei.timetable.listener.ISchedule;
import com.zhuangfei.timetable.listener.OnSlideBuildAdapter;
import com.zhuangfei.timetable.model.Schedule;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import butterknife.BindView;
import cn.cqautotest.cqviehelper.R;
import cn.cqautotest.cqviehelper.base.BaseActivity;
import cn.cqautotest.cqviehelper.base.BaseFragment;
import cn.cqautotest.cqviehelper.config.Constants;
import cn.cqautotest.cqviehelper.interfaces.IAppDataCallback;
import cn.cqautotest.cqviehelper.interfaces.ICourseCallback;
import cn.cqautotest.cqviehelper.presenter.CoursePresenter;
import cn.cqautotest.cqviehelper.presenter.UpdateAppDataPresenter;
import cn.cqautotest.cqviehelper.ui.activity.HomeActivity;
import cn.cqautotest.cqviehelper.ui.activity.ScanQrCodeActivity;
import cn.cqautotest.cqviehelper.ui.dialog.ConfirmDialog;
import cn.cqautotest.cqviehelper.utils.ColorPool;
import cn.cqautotest.cqviehelper.utils.LogUtils;
import cn.cqautotest.cqviehelper.utils.MyScheduleSupport;
import cn.cqautotest.cqviehelper.views.ClassDetailPopWindow;
import cn.cqautotest.cqviehelper.views.MyTimetableView;
import cn.cqautotest.cqviehelper.views.TitleBarView;
import cn.cqautotest.cqviehelper.views.calendar.MyWeekView;

@SuppressLint("NonConstantResourceId")
@RequiresApi(api = Build.VERSION_CODES.O)
public class SchoolTimetableFragment extends BaseFragment<BaseActivity> implements ICourseCallback, IAppDataCallback {

    @BindView(R.id.titleBar)
    TitleBarView mTitleBar;
    @BindView(R.id.weekView)
    MyWeekView mWeekView;
    @BindView(R.id.refreshLayout)
    TwinklingRefreshLayout mRefreshLayout;
    @BindView(R.id.timetableView)
    MyTimetableView mTimetableView;
    private ClassDetailPopWindow mClassDetailPopWindow = null;
    private ConfirmDialog mDeleteCourseDialog = null;
    private ConfirmDialog mChangeWeekDialog = null;
    private CoursePresenter mCoursePresenter = null;
    private int requestErrorCount = 0;
    private String mUserId = "";
    private String mSchoolYear = "";
    private int mTerm = 1;
    private int mCurrentWeek = 1;
    private int tempWeek = mCurrentWeek;
    private final List<Schedule> mSchedules = new ArrayList<>();
    private final List<String> schoolYearList = new ArrayList<>();
    private int mMaxSlideItem = 12;
    private List<String> mPermissions = new ArrayList<>();
    private OnSlideBuildAdapter mSlideBuildAdapter;
    private UpdateAppDataPresenter mUpdateAppDataPresenter;

    public static SchoolTimetableFragment getInstance() {
        return new SchoolTimetableFragment();
    }

    @Override
    protected int getLayoutResId() {
        return R.layout.fragment_school_timetable;
    }

    @Override
    protected void initPresenter() {
        mUpdateAppDataPresenter = UpdateAppDataPresenter.getInstance();
        mUpdateAppDataPresenter.registered(this);
        mUpdateAppDataPresenter.updateSidebarTime();
        mCoursePresenter = CoursePresenter.getInstance();
        mCoursePresenter.registered(this);
        mCoursePresenter.onUserInfoChanged();
    }

    @Override
    protected void initView(View rootView) {
        //暂时隐藏右侧的工具栏标签
        mTitleBar.findViewById(R.id.ivAdd).setVisibility(View.GONE);
        mRefreshLayout.setEnableLoadmore(false);
        mRefreshLayout.setHeaderView(new BezierLayout(getContext()));
        mWeekView.isShow(false).showView();
        mTimetableView.alpha(0, 0, 1)
                .maxSlideItem(mMaxSlideItem).isShowNotCurWeek(false).showView();
        FragmentActivity activity = getAttachActivity();
        Window window = activity.getWindow();
        mClassDetailPopWindow = new ClassDetailPopWindow(mContext, window);
        //目前默认不可编辑课程
        mClassDetailPopWindow.setCourseEnabled(false);
        mDeleteCourseDialog = new ConfirmDialog(mContext);
        mDeleteCourseDialog.setContentView(R.layout.dialog_confirm_del_course);
        mChangeWeekDialog = new ConfirmDialog(mContext);
        mChangeWeekDialog.setContentView(R.layout.dialog_confirm_change_current_week);
    }

    @Override
    public void reSetUpUserInfo() {
        mUserId = mSpUserInfoSetting.getString(Constants.USER_ID, "");
        mSchoolYear = mSpUserInfoSetting.getString(Constants.SCHOOL_YEAR, "2021-2022");
        mTerm = mSpUserInfoSetting.getInt(Constants.TERM, 1);
        long termStartTimestamp = mSpUserInfoSetting.getLong(Constants.START_DATE, System.currentTimeMillis());
        mCurrentWeek = MyScheduleSupport.timeTransform(termStartTimestamp);
        mMaxSlideItem = mSpUserInfoSetting.getInt(Constants.MAX_NUMBER_COURSES, 12);
        LogUtils.d(this, "reSetUpUserInfo: =====> mUserId is " + mUserId);
        LogUtils.d(this, "reSetUpUserInfo: =====> mSchoolYear is " + mSchoolYear);
        LogUtils.d(this, "reSetUpUserInfo: =====> mCurrentWeek is " + mCurrentWeek);
        mTitleBar.setTermText(String.format("%s 第%1s学期", mSchoolYear, mTerm));
        mRefreshLayout.startRefresh();
        if (!isCompleteInfo()) {
            ToastUtils.showLong("个人信息尚未完善，请检查！");
        }
    }

    /**
     * 返回用户信息是否完整
     *
     * @return isCompleteInfo
     */
    private boolean isCompleteInfo() {
        return !(TextUtils.isEmpty(mUserId) || TextUtils.isEmpty(mSchoolYear));
    }

    @Override
    protected void initEvent() {
        mTitleBar.setOnItemLongClickBaseListener(new TitleBarView.OnItemLongClickListener() {
            @Override
            public boolean onChangeWeekLongClick(boolean isShowing) {
                //选择学期
                chooseSchoolYear();
                //ToastUtils.showShort("选择学期");
                return true;
            }
        });
        //标题栏的点击回调通知
        mTitleBar.setOnItemClickBaseListener(new TitleBarView.OnItemClickListener() {
            @Override
            public void onScannerClick() {
                checkPermissions();
            }

            @Override
            public void onChangeWeekClick(boolean isShowing) {
                mWeekView.isShow(isShowing).scrollToPerLayout();
                //在周次选择视图被隐藏时，重新显示当前周的课程
                if (!isShowing) {
                    mTimetableView.onDateBuildListener().onUpdateDate(mCurrentWeek, tempWeek);
                    mTimetableView.changeWeekOnly(mCurrentWeek);
                }
            }

            @Override
            public void onAddClick() {
                ToastUtils.showShort("该功能正在抓紧开发中~");
            }
        });
        mRefreshLayout.setOnRefreshListener(new RefreshListenerAdapter() {
            @Override
            public void onRefresh(TwinklingRefreshLayout refreshLayout) {
                //重新获取当前周次的课程数据
                if (mCoursePresenter != null && mTitleBar != null && mWeekView != null && mTimetableView != null) {
                    //默认获取当前周次的课程数据（如果没有，则加载本地缓存的课程数据）
                    mCoursePresenter.getCourseByWeek(mUserId, mSchoolYear, mTerm, mCurrentWeek);
                    mWeekView.isShow(false).showView();
                    mTitleBar.setShowing(false);
                    mTitleBar.setWeekText(String.format("第%s周", mTimetableView.curWeek()), Color.BLACK);
                }
            }
        });
        mWeekView.callback(week -> {
            //临时显示选中周次的课程
            tempWeek = week;
            mTimetableView.onDateBuildListener().onUpdateDate(mCurrentWeek, tempWeek);
            mTimetableView.changeWeekOnly(tempWeek);
            updateWeekUI();
        });
        mWeekView.callback(() -> mChangeWeekDialog.show());
        //设置侧边栏的时间
        mSlideBuildAdapter = (OnSlideBuildAdapter) mTimetableView.onSlideBuildListener();
        mSlideBuildAdapter.setTimeTextColor(Color.WHITE).setTimes(MyScheduleSupport.getDefaultSlideTimes());
        //点击课程时弹出课程详情
        mTimetableView.callback((ISchedule.OnItemClickListener) (v, scheduleList) -> {
            if (mClassDetailPopWindow != null) {
                mClassDetailPopWindow.setScheduleList(scheduleList).showAtLocation(getView(), Gravity.BOTTOM, 0, 0);
                mClassDetailPopWindow.startEnterAnim();
            }
        });
        //长按课程时弹出课程删除对话框
        mTimetableView.callback((ISchedule.OnItemLongClickListener) (v, day, start) -> {
            // TODO: 2020/9/8 暂时不添加删除课程功能，因为是从服务器获取最新的课程。
            //if (mDeleteCourseDialog != null) {
            //    mDeleteCourseDialog.show();
            //}
        });
        //旗标布局的点击监听
        mTimetableView.callback((ISchedule.OnFlaglayoutClickListener) (day, start) -> {
            //if (mClassDetailPopWindow != null) {
            //    mClassDetailPopWindow.resetSchedule().showAtLocation(getView(), Gravity.BOTTOM, 0, 0);
            //    //修改背景的透明度，有一个渐变的过程
            //    mClassDetailPopWindow.startEnterAnim();
            //}
        });
        //pop窗体消失时的监听
        mClassDetailPopWindow.setOnDismissListener(() -> {
            if (mClassDetailPopWindow != null) {
                Schedule schedule = mClassDetailPopWindow.getSchedule();
                LogUtils.d(this, "initListener: =============" + new Gson().toJson(schedule));
                //pop窗体消失以后，恢复透明度
                mClassDetailPopWindow.startOutAnim();
            }
        });
        //设置确认对话框的监听
        mDeleteCourseDialog.setOnDialogActionClickListener(new ConfirmDialog.OnDialogActionSimpleListener() {
            @Override
            public void onConfirmClick() {
                // TODO: 2020/8/4 执行删除课程的操作
                ToastUtils.showShort("删除课程");
            }

            @Override
            public void onGiveUpClick() {
                ToastUtils.showShort("放弃删除");
            }
        });
        mChangeWeekDialog.setOnDialogActionClickListener(new ConfirmDialog.OnDialogActionSimpleListener() {

            @Override
            public void onConfirmClick() {
                if (mTimetableView != null && mRefreshLayout != null) {
                    //当前周次发生了变化，获取当前周次最新的课程数据
                    mCurrentWeek = tempWeek;
                    mTimetableView.changeWeekForce(mCurrentWeek);
                    long timestamp = MyScheduleSupport.getAFewWeeksBeforeTimestamp(System.currentTimeMillis(), mCurrentWeek);
                    Log.d(TAG, "onConfirmClick: ====> convert before " + System.currentTimeMillis());
                    Log.d(TAG, "onConfirmClick: ====> convert after  " + timestamp);
                    mSpUserInfoSetting.edit().putLong(Constants.START_DATE, timestamp).apply();
                    mWeekView.curWeek(mCurrentWeek).updateView();
                    mTimetableView.curWeek(mCurrentWeek).updateView();
                    updateWeekUI();
                    ToastUtils.showShort("正在拉取课程数据...");
                    mRefreshLayout.startRefresh();
                }
            }

            @Override
            public void onGiveUpClick() {
                ToastUtils.showShort("放弃修改");
            }
        });
    }

    /**
     * 选择学期
     */
    private void chooseSchoolYear() {
        OptionsPickerBuilder schoolYearBuilder = new OptionsPickerBuilder(mContext, (options1, options2, options3, v) -> {
            mSchoolYear = schoolYearList.get(options1);
            mTerm = options2 + 1;
            mSpUserInfoSetting.edit().putString(Constants.SCHOOL_YEAR, mSchoolYear).apply();
            mSpUserInfoSetting.edit().putInt(Constants.TERM, mTerm).apply();
            LogUtils.d(this, "chooseSchoolYear: ====> mSchoolYear is " + mSchoolYear);
            LogUtils.d(this, "chooseSchoolYear: ====> mTerm is " + mTerm);
            if (mCoursePresenter != null) mCoursePresenter.onUserInfoChanged();
        }).isAlphaGradient(true);
        OptionsPickerView<String> schoolYearOptions = schoolYearBuilder.build();
        List<List<String>> objects = new ArrayList<>();
        for (int i = 0; i < schoolYearList.size(); i++) {
            List<String> termList = new ArrayList<>();
            termList.add("第1学期");
            termList.add("第2学期");
            objects.add(termList);
        }
        schoolYearOptions.setPicker(schoolYearList, objects);
        schoolYearOptions.show();
    }

    /**
     * 更新周次标题栏的UI
     */
    private void updateWeekUI() {
        if (tempWeek == mTimetableView.curWeek()) {
            //如果是本周则设置为黑色字体，否则为红色
            mTitleBar.setWeekText(String.format("第%s周", tempWeek), Color.BLACK);
        } else {
            mTitleBar.setWeekText(String.format("第%s周(非本周)", tempWeek), Color.RED);
        }
    }

    //最后点击二维码扫描按钮的时间
    private long scanLastTime = 0;

    /**
     * 检查权限是否获取，否则不进行跳转
     */
    private void checkPermissions() {
        long currentTime = System.currentTimeMillis();
        //如果上一次点击和本次点击的时间差值小于1秒，则不响应事件
        if (currentTime - scanLastTime < 1000) return;
        scanLastTime = System.currentTimeMillis();
        XXPermissions.with(getActivity()).permission(mPermissions)
                .request(new OnPermission() {
                    @Override
                    public void hasPermission(List<String> granted, boolean isAll) {
                        if (isAll) {
                            startActivity(new Intent(getActivity(), ScanQrCodeActivity.class));
                        } else {
                            ToastUtils.showShort("您还没有授予权限！");
                        }
                    }

                    @Override
                    public void noPermission(List<String> denied, boolean quick) {
                        if (quick) {
                            LogUtils.d(this, "noPermission: ==========> 权限被永久拒绝了！");
                        }
                        XXPermissions.gotoPermissionSettings(Objects.requireNonNull(getContext()));
                    }
                });
    }

    @Override
    protected void initData() {
        mPermissions = ArrayUtils.asArrayList(Permission.Group.STORAGE);
        mPermissions.add(Manifest.permission.CAMERA);
        mPermissions.add(Manifest.permission.ACCESS_WIFI_STATE);
        mPermissions.add(Permission.READ_PHONE_STATE);
        reSetUpUserInfo();
        schoolYearList.add("2021-2022");
        schoolYearList.add("2020-2021");
    }

    @Override
    public void onPause() {
        super.onPause();
        mRefreshLayout.finishRefreshing();
    }

    /**
     * 在界面重新可见的时候更改页面的主题
     */
    @Override
    protected void uiReShowing() {
        setSchedule(mCoursePresenter.deduplication());
        FragmentActivity activity = getActivity();
        if (activity instanceof HomeActivity) {
            HomeActivity homeActivity = (HomeActivity) activity;
            homeActivity.clearBgState();
            homeActivity.getDecorView().setBackgroundResource(R.mipmap.img_class_schedule_bg);
        }
    }

    /**
     * 课程数据加载完毕的回调通知
     *
     * @param schedules 本学期的所有课程数据
     */
    @Override
    public void onCourseLoaded(List<Schedule> schedules) {
        //请求成功时，将错误统计次数清零
        requestErrorCount = 0;
        mSchedules.clear();
        mSchedules.addAll(schedules);
        //随机设置课程的颜色
        setForColors();
        if (mWeekView != null && mTimetableView != null) {
            setSchedule(mCoursePresenter.deduplication());
        }
        //结束刷新状态
        if (mRefreshLayout != null) mRefreshLayout.finishRefreshing();
    }

    /**
     * 指定课程的颜色，未指定的课程自动分配
     */
    private void setForColors() {
        ArrayMap<String, Integer> colorMap = new ArrayMap<>();
        for (Schedule schedule : mSchedules) {
            colorMap.put(schedule.getName(), ColorPool.getRandomColor());
        }
        if (mTimetableView != null) {
            mTimetableView.colorPool().clear().setIgnoreUserlessColor(false).setColorMap(colorMap);
        }
    }

    /**
     * 当请求失败时的回调通知（网络错误/服务器异常）
     *
     * @param e
     */
    @Override
    public void onRequestError(Exception e) {
        if (mRefreshLayout != null) mRefreshLayout.finishRefreshing();
        requestErrorCount++;
        //允许三次错误请求重试
        if (requestErrorCount > 3) {
            if (mCoursePresenter != null) {
                setSchedule(mCoursePresenter.deduplication());
            }
            ToastUtils.showLong("课程获取超三次失败！");
            return;
        }
        //防止短时间内频繁请求
        mHandler.postDelayed(() -> {
            if (mCoursePresenter != null) mCoursePresenter.reGetCourse();
        }, 1000);
        //当依附的Activity在前台时才进行提示，否则不进行提示
        if (getAttachActivity().isFront()) {
            ToastUtils.showShort("课程获取超时，正在重试~");
        }
    }

    private boolean isFirst = true;

    /**
     * 设置课程列表的数据
     */
    private void setSchedule(List<Schedule> schedules) {
        if (mWeekView == null || mTimetableView == null) return;
        if (isFirst) {
            mWeekView.data(schedules).curWeek(mCurrentWeek).showView();
            mTimetableView.data(schedules).curWeek(mCurrentWeek).showView();
            isFirst = false;
        } else {
            mWeekView.data(schedules).curWeek(mCurrentWeek).updateView();
            mTimetableView.data(schedules).curWeek(mCurrentWeek).updateView();
        }
    }

    @Override
    protected void release() {
        mClassDetailPopWindow = null;
        if (mUpdateAppDataPresenter != null) mUpdateAppDataPresenter.unRegistered(this);
        if (mCoursePresenter != null) mCoursePresenter.unRegistered(this);
    }

    /**
     * 侧边栏时间在线更新的回调
     *
     * @param times 侧边栏时间的数据源
     */
    @Override
    public void onSidebarTimeUpdate(String[] times) {
        if (mSlideBuildAdapter != null) {
            mSlideBuildAdapter.setTimeTextColor(Color.WHITE).setTimes(times);
        }
    }

    @Override
    public void onSchoolCalendarUpdate(Map<String, Calendar> calendarMap) {

    }

    @Override
    public void onPostContentUpdate(String postContent) {

    }
}
